#include "treeviewmodel.h"
#include <itpp/itbase.h>
#include "treeitem.h"

#include <QStringList>
#include <float.h>

TreeViewModel::TreeViewModel(QList<GSData *> *pDataSet, QObject *parent) :
    QAbstractItemModel(parent)
{
//    this->pDataSet = pDataSet;
    rootData << "Name" << "Type" << "Value" << "Min" << "Max";
    rootItem = new TreeItem(rootData);

    setupModelData(pDataSet, rootItem);
}

TreeViewModel::~TreeViewModel()
{
    delete rootItem;
}

int TreeViewModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
    else
        return rootItem->columnCount();
}

QVariant TreeViewModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (role != Qt::DisplayRole)
        return QVariant();

    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

    return item->data(index.column());
}

Qt::ItemFlags TreeViewModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;

    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant TreeViewModel::headerData(int section, Qt::Orientation orientation,
                               int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return rootItem->data(section);

    return QVariant();
}

QModelIndex TreeViewModel::index(int row, int column, const QModelIndex &parent)
            const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    TreeItem *parentItem;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<TreeItem*>(parent.internalPointer());

    TreeItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}

QModelIndex TreeViewModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
    TreeItem *parentItem = childItem->parent();

    if (parentItem == rootItem)
        return QModelIndex();

    return createIndex(parentItem->row(), 0, parentItem);
}

int TreeViewModel::rowCount(const QModelIndex &parent) const
{
    TreeItem *parentItem;
    if (parent.column() > 0)
        return 0;

    if (!parent.isValid())
        parentItem = rootItem;
    else
        parentItem = static_cast<TreeItem*>(parent.internalPointer());

    return parentItem->childCount();
}

QList<QVariant> TreeViewModel::getDataInfo(GSData* pdata)
{
    QList<QVariant> columnData;
    columnData << pdata->name;
    double mmin, mmax, temp;
    mmin = DBL_MAX; mmax = DBL_MIN;
    switch (pdata->inDataType) {
    case GSData::VECTOR:
        columnData << tr("Vector");
        columnData << tr("<%1x1 double>").arg(pdata->vecData.length());
        columnData << tr("%1").arg(min(pdata->vecData));
        columnData << tr("%1").arg(max(pdata->vecData));
        break;
    case GSData::MATRIX:
        columnData << tr("Matrix");
        columnData << tr("<%1x%2 double>").arg(pdata->matData.rows())
                                          .arg(pdata->matData.cols());
        columnData << tr("%1").arg(min(min(pdata->matData)));
        columnData << tr("%1").arg(max(max(pdata->matData)));
        break;
    case GSData::ARRAY_VEC:
        columnData << tr("Array Vector");
        columnData << tr("<%1 Vec>").arg(pdata->arrayVecData.length());        
        for(int i=0; i<pdata->arrayVecData.length();i++)
        {
            temp = min(pdata->arrayVecData(i));
            mmin = (temp < mmin) ? temp:mmin;
            temp = max(pdata->arrayVecData(i));
            mmax = (temp > mmax) ? temp:mmax;
        }
        columnData << tr("%1").arg(mmin);
        columnData << tr("%1").arg(mmax);
        break;
    case GSData::ARRAY_MAT:
        columnData << tr("Array Matrix");
        columnData << tr("<%1 Mat>").arg(pdata->arrayMatData.length());
        for(int i=0; i<pdata->arrayMatData.length();i++)
        {
            temp = min(min(pdata->arrayMatData(i)));
            mmin = (temp < mmin) ? temp:mmin;
            temp = max(max(pdata->arrayMatData(i)));
            mmax = (temp > mmax) ? temp:mmax;
        }
        columnData << tr("%1").arg(mmin);
        columnData << tr("%1").arg(mmax);
        break;
    case GSData::STRING:
        columnData << tr("String");
        columnData << tr("<1x1 String>");
        columnData << tr("NULL");
        columnData << tr("NULL");
        break;
    }
    return columnData;
}

void TreeViewModel::refreshDataView(QList<GSData *> *pDataSet)
{
    rootItem->removeAllChild();
    setupModelData(pDataSet, rootItem);
}

void TreeViewModel::setupModelData(QList<GSData *> *pDataSet, TreeItem *parent)
{
    QList<TreeItem*> parents;
    parents << parent;

    for(int i=0; i<pDataSet->length(); i++)
    {
        QList<QVariant> columnData = getDataInfo(pDataSet->at(i));

//        if (//is child) && (parents.last()->childCount() > 0)
//        {
            // The last child of the current parent is now the new parent
            // unless the current parent has no children.
//          parents << parents.last()->child(parents.last()->childCount()-1);
//        }

        // Append a new item to the current parent's list of children.
        parents.last()->appendChild(new TreeItem(columnData, parents.last()));
    }
}
